/**
 * <br>
 * <b>@Title: </b>BeanToInterface.java<br>
 * <b>@Package: </b>com.xd100.lzll.gm.util.beantointerface<br>
 * <b>功能：</b>详细的功能描述<br>
 * <b>作者：</b>xiaoyu Mo (liujun)<br>
 * <b>日期：</b>2015-5-5 下午7:52:45 <br>
 * <b>版权所有：<b>版权所有(C) 2014，QQ 328321146<br>
 */
package com.xd100.lzll.gm.util.beantointerface;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * <br>
 * <b>@ClassName: </b>BeanToInterface<br>
 * <b>@Package: </b>com.xd100.lzll.gm.util.beantointerface<br>
 * <b>功能：Bean生成接口</b><br>
 * <b>作者：</b>xiaoyu Mo (liujun)<br>
 * <b>日期：</b>2015-5-5 下午7:52:45 <br>
 * <b>版权所有：<b>版权所有(C) 2014，QQ 328321146<br>
 */
public class BeanToInterface {
	
	static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	/**
	 * <br>
	 * <b>@Title: </b>getMethodStr<br>
	 * <b>@Package: </b>com.xd100.lzll.gm.util.beantointerface<br>
	 * <b>功能：接口方法构造</b><br>
	 * <b>@param: </b>@param beanInfo
	 * <b>@param: </b>@param className
	 * <b>@param: </b>@return
	 * <b>@param: </b>@throws Exception <br>
	 * <b>作者：</b>xiaoyu Mo (liujun)<br>
	 * <b>日期：</b>2015-5-6 下午12:23:00 <br>
	 * <b>@return:</b>String<br>
	 * <b>版权所有：<b>版权所有(C) 2014，QQ 328321146<br>
	 */
	private static String getMethodStr(BeanInfo beanInfo, String className) throws Exception{
		StringBuilder get = new StringBuilder("\tpublic List<" + className + "> query" + className);
		// 给 JavaBean 对象的属性赋值
		PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
		get.append("(");
		if (propertyDescriptors != null) {
			for (int i = 0; i < propertyDescriptors.length; i++) {
				PropertyDescriptor descriptor = propertyDescriptors[i];
				Object obj = descriptor.getPropertyType();// 获取属性的class对象
				String typeName = "";
				if(obj.toString().equals("int")){
					typeName = "java.lang.Integer";
				} else if(obj.toString().equals("boolean")){
					typeName = "java.lang.Boolean";
				} else {
//					typeName = obj.getClass().getName();// 获取属性类型名称  此处获取的一直是java.lang.Class 原因不明
					typeName = obj.toString().replace("class ", "");
				}
				String propertyName = descriptor.getName();// 获取属性名
				if(!propertyName.equals("class")){
					if (i == propertyDescriptors.length - 1) {// 最后一个不要逗号
						get.append(typeName + " " + propertyName);
					} else {
						get.append(typeName + " " + propertyName + ", ");
					}
				}
			}
		}
		//get.append(") throws Exception;");//接口
		get.append(") throws Exception{return null;}");//实现
		return get.toString();
	}

	/**
	 * <br>
	 * <b>@Title: </b>removeFileNameHouZui<br>
	 * <b>@Package: </b>com.xd100.lzll.gm.util.beantointerface<br>
	 * <b>功能：去掉文件后缀</b><br>
	 * <b>@param: </b>@param fileName
	 * <b>@param: </b>@return
	 * <b>@param: </b>@throws Exception <br>
	 * <b>作者：</b>xiaoyu Mo (liujun)<br>
	 * <b>日期：</b>2015-5-6 下午12:22:38 <br>
	 * <b>@return:</b>String<br>
	 * <b>版权所有：<b>版权所有(C) 2014，QQ 328321146<br>
	 */
	public static String removeFileNameHouZui(String fileName) throws Exception{
		return fileName.substring(0, fileName.lastIndexOf("."));
	}
	
	/**
	 * 根据文件夹路径，读取所有子目录里包含指定类型的文件。
	 * 
	 * @param dirPath
	 *            <li>
	 *            eg:E:\app\agreeWeb\workagree\fly.info\context\images\fly\信息发布
	 *            \2012\02\08\02\32\27\227\89857567\</li>
	 * @param fileTypes
	 *            <li>eg:jpg,gif,jpeg,bmp</li>
	 * @return 所有符合指定类型文件的文件路径 <li>
	 *         eg:E:\app\agreeWeb\workagree\fly.info\context\
	 *         images\fly\信息发布\2012\02\08\02\32\27\227\89857567\-1\1-1-2\1.gif</li>
	 */
	private static List<String> getAllFilePathByDir_FilterByFileType(String dirPath, List<String> fileTypes) {
		String localClassFilePath = BeanToInterface.class.getResource("/").getPath();
		System.out.println(localClassFilePath);
		String contextFilePath = localClassFilePath.substring(1, localClassFilePath.length() - 16);
		contextFilePath = contextFilePath.replace("/", "\\");
		System.out.println(contextFilePath);

		List<String> filePathList = new ArrayList<String>();
		for (int index = 0; index < fileTypes.size(); index++) {
			List<String> arrayList = BeanToInterface.getListFiles(dirPath, fileTypes.get(index), true);
			if (arrayList.isEmpty()) {
				System.out.println("没有符号要求的文件");
			} else {
				System.out.println("符号要求的文件数：" + arrayList.size());
				for (Iterator<String> i = arrayList.iterator(); i.hasNext();) {
					String temp = (String) i.next();
					// E:\app\agreeWeb\workagree\fly.info\context\images\fly\信息发布\2012\02\08\06\05\06\26\90852629\1-1\1-1-1\1.jpg
					temp = temp.replace(contextFilePath, "");// 把根路径去掉
					filePathList.add(temp);
				}
			}
		}
		for (int replaceIndex = 0; replaceIndex < filePathList.size(); replaceIndex++) {
			filePathList.set(replaceIndex, filePathList.get(replaceIndex).replace("\\", "/"));
		}
		return filePathList;
	}

	/**
	 * 
	 * @param path
	 *            文件路径
	 * @param suffix
	 *            后缀名
	 * @param isdepth
	 *            是否遍历子目录
	 * @return 文件路径
	 */
	private static List<String> getListFiles(String path, String suffix, boolean isdepth) {
		List<String> fileList = new ArrayList<String>();
		File file = new File(path);
		return BeanToInterface.listFile(file, suffix, isdepth, fileList);
	}

	private static List<String> listFile(File file, String suffix, boolean isdepth, List<String> fileList) {
		// 是目录，同时需要遍历子目录
		if (file.isDirectory() && isdepth == true) {
			File[] t = file.listFiles();
			for (int i = 0; i < t.length; i++) {
				listFile(t[i], suffix, isdepth, fileList);
			}
		} else {
			String filePath = file.getAbsolutePath();
			if (suffix != null) {
				int begIndex = filePath.lastIndexOf(".");// 最后一个.(即后缀名前面的.)的索引
				String tempsuffix = "";
				if (begIndex != -1)// 防止是文件但却没有后缀名结束的文件
				{
					tempsuffix = filePath.substring(begIndex + 1, filePath.length());
				}
				if (tempsuffix.equals(suffix)) {
					fileList.add(filePath);
				}
			} else {
				// 后缀名为null则为所有文件
				fileList.add(filePath);
			}
		}
		return fileList;
	}
	
	/**
	 * <br>
	 * <b>@Title: </b>lowerFirestChar<br>
	 * <b>@Package: </b>com.xd100.lzll.gm.util.beantointerface<br>
	 * <b>功能：首字母小写</b><br>
	 * <b>@param: </b>@param src
	 * <b>@param: </b>@return <br>
	 * <b>作者：</b>xiaoyu Mo (liujun)<br>
	 * <b>日期：</b>2015-5-6 下午3:46:34 <br>
	 * <b>@return:</b>String<br>
	 * <b>版权所有：<b>版权所有(C) 2014，QQ 328321146<br>
	 */
	private static String lowerFirestChar(String src) {
		return src.substring(0, 1).toLowerCase().concat(src.substring(1));
	}

	/**
	 * <br>
	 * <b>@Title: </b>classConvertInterface<br>
	 * <b>@Package: </b>com.xd100.lzll.gm.util.beantointerface<br>
	 * <b>功能：生成接口</b><br>
	 * <b>@param: </b>@param beanPackPath  
	 * 					<li>bean的绝对路径  如"E:\\workspace\\RPGGM_CN_new\\src\\com\\xd100\\lzll\\gm\\bean"</li>
	 * <b>@param: </b>@param interFacePackPath 
	 * 					<li>生成接口的绝对路径 如"E:\\workspace\\RPGGM_CN_new\\src\\com\\xd100\\lzll\\gm\\access"</li>
	 * <b>@param: </b>@param beanPack 
	 * 					<li>bean包在程序中的路径 如"com.xd100.lzll.gm.bean"</li>
	 * <b>@param: </b>@param interfacePack 
	 * 					<li>interface包在程序中的路径 如"com.xd100.lzll.gm.access"</li>
	 * <b>@param: </b>@param interfaceHouZui 
	 * 					<li>interfaceHouZui 接口后缀 如 AccessIF</li>
	 * <b>@param: </b>@throws Exception
	 * <b>作者：</b>xiaoyu Mo (liujun)<br>
	 * <b>日期：</b>2015-5-6 下午12:14:33 <br>
	 * <b>@return:</b>void<br>
	 * <b>版权所有：<b>版权所有(C) 2014，QQ 328321146<br>
	 */
	@SuppressWarnings("rawtypes")
	public static void classConvertInterface(String beanPackPath, String interFacePackPath, String beanPack, String interfacePack, String interfaceHouZui) throws Exception {
		List<String> fileTypes = new ArrayList<String>();
		fileTypes.add("java");//内部强制选择java文件进行
		List<String> filePath = BeanToInterface.getAllFilePathByDir_FilterByFileType(beanPackPath, fileTypes);
		File dir = new File(interFacePackPath);
		if (!dir.exists()) {
			dir.mkdirs();// 生成的目录包括父目录
		}
		String outputdir = dir.getAbsolutePath();
		if(!filePath.isEmpty()){
			for(String path:filePath){
				File file = new File(path);
				if (!file.isFile()) {//是文件
					String javaFileName = removeFileNameHouZui(file.getName());// 去掉.java
					Class type = Class.forName(beanPack + "." + javaFileName);// 从包名中获取类
					BeanInfo beanInfo = Introspector.getBeanInfo(type); // 获取类属性
					StringBuilder classInfo = new StringBuilder("\t/**\r\n\t*");
					classInfo.append("此接口由" + BeanToInterface.class.getSimpleName() + "工具自动生成\r\n");
					classInfo.append("\t*备注(数据表的comment字段)：");
					classInfo.append("\r\n");
					classInfo.append("\t*@author 328321146@qq.com\r\n");
					classInfo.append("\t*@since ");
					classInfo.append(sdf.format(new Date()));
					classInfo.append("\r\n\t*/\r\n\r\n");
					
					//======================================
//					classInfo.append("\r@Repository(\""+lowerFirestChar(javaFileName + interfaceHouZui)+"\")//代表持久层  不写括号的 默认类名 首字母小写 \r\n");//access实现加上
					classInfo.append("\r@Service(\""+lowerFirestChar(javaFileName + interfaceHouZui)+"\")//代表服务层  不写括号的 默认类名 首字母小写 \r\n");//sercice实现加上
					//======================================
					
					classInfo.append("\tpublic class ").append(javaFileName + interfaceHouZui);
					
					//======================================
					classInfo.append(" implements ").append(javaFileName + interfaceHouZui + "IF");//实现加上实现的接口
					//======================================
					
					classInfo.append("{\r\n");// 设置接口名
					
					//======================================
					//注入连接 access实现加上
//					classInfo.append("@Autowired @Qualifier(\"jdbctemplate\")\r\nprivate JdbcTemplate jdbctemplate;\r\n");// 
					//服务层注入持久层加上
					classInfo.append("@Autowired @Qualifier(\""+lowerFirestChar(javaFileName + interfaceHouZui)+"\")\r\nprivate "+javaFileName + interfaceHouZui+"IF "+lowerFirestChar(javaFileName + interfaceHouZui)+";\r\n");// 
					//======================================
					
					StringBuilder methods = new StringBuilder();
					methods.append(getMethodStr(beanInfo, javaFileName));// 设置接口方法
					classInfo.append(methods);
					classInfo.append("\r\n");
					classInfo.append("}");
					String packageinfoInterface = "package "+interfacePack+";\r\n\r\n";// 设置接口包
					String packageinfoClass = "import "+ beanPack +"." + javaFileName+";\r\n\r\n";// 导入类
					packageinfoClass = packageinfoClass + "import java.util.List;\r\n\r\n";// 导入类
					
					//======================================
					//注入access加上
//					packageinfoClass = packageinfoClass + "import org.springframework.beans.factory.annotation.Autowired;\r\n\r\n"+
//							"import org.springframework.beans.factory.annotation.Qualifier;\r\n\r\n"+
//							"import org.springframework.jdbc.core.JdbcTemplate;\r\n\r\n"+
//							"import org.springframework.stereotype.Repository;\r\n\r\n";// 导入类
					//注入service加上
					packageinfoClass = packageinfoClass + "import org.springframework.beans.factory.annotation.Autowired;\r\n\r\n"+
							"import org.springframework.beans.factory.annotation.Qualifier;\r\n\r\n"+
							"import org.springframework.stereotype.Service;\r\n\r\n";// 导入类
					//======================================
					
					
					File tempfile = new File(outputdir, javaFileName + interfaceHouZui + ".java");// 生成接口文件
					try {
						FileWriter fw = new FileWriter(tempfile);
						fw.write(packageinfoInterface);
						fw.write(packageinfoClass);
						fw.write(classInfo.toString());
						fw.flush();
						fw.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				} else if (file.isDirectory()) {//不是文件
					
				}
			}
		}
	}
	
	public static void main(String[] args) throws Exception{
		classConvertInterface("E:\\workspace\\RPGGM_CN_new\\src\\com\\xd100\\lzll\\gm\\bean", "E:\\workspace\\RPGGM_CN_new\\src\\com\\xd100\\lzll\\gm\\service\\impl","com.xd100.lzll.gm.bean", "com.xd100.lzll.gm.service.impl", "Service");
	}

}
